﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
//using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
//using Newtonsoft.Json;
using System.Globalization;
using System.IO;
using Renci.SshNet;
using OxyPlot;
using OxyPlot.WindowsForms;
using OxyPlot.Annotations;
using OxyPlot.Axes;
using OxyPlot.Reporting;
using OxyPlot.Series;
//using RestSharp;
//using RestSharp.Deserializers;
//using Newtonsoft.Json.Linq;
using System.Deployment.Application;
using System.Reflection;

namespace MeasNetClient
{
    public partial class FormPlayground : Form
    {
        
        //Dictionary<string, string> MaintCommandsList = new Dictionary<string, string>()
        //{
        //    {"System Name", "uname -a"},
        //    {"System Uptime", "uptime"},
        //    {"System Time", "date"},
        //    {"Installed packages", "dpkg -l | grep ii"},
        //    {"System restart", "sudo reboot"},
        //    //{"Check RTLSDR dongle", "rtl_test -t"}
        //};

        Dictionary<string, string> RFGainList = new Dictionary<string, string>()
        {
            {"Automatic", "0"},
            {"0.9", "0.9"},
            {"1.4", "1.4"},
            {"2.7", "2.7"},
            {"3.7", "3.7"},
            {"7.7", "7.7"},
            {"8.7", "8.7"},
            {"12.5", "12.5"},
            {"14.4", "14.4"},
            {"15.7", "15.7"},
            {"16.6", "16.6"},
            {"19.7", "19.7"},
            {"20.7", "20.7"},
            {"22.9", "22.9"},
            {"25.4", "25.4"},
            {"28.0", "28.0"},
            {"29.7", "29.7"},
            {"32.8", "32.8"},
            {"33.8", "33.8"},
            {"36.4", "36.4"},
            {"37.2", "37.2"},
            {"38.6", "38.6"},
            {"40.2", "40.2"},
            {"42.1", "42.1"},
            {"43.4", "43.4"},
            {"43.9", "43.9"},
            {"44.5", "44.5"},
            {"48.0", "48.0"},
            {"49.6", "49.6"},
        };

        Dictionary<string, string> AudioCodecList = new Dictionary<string, string>()
        {
            {"FLAC Free Lossless Audio Codec", "flac"},
            {"OGG Vorbis", "vorb"},
            //{"MPEG audio layer 2", "mpga"},
            //{"AC3 sound", "ac3"},
            {"RAW (to file)", "raw"}, // Not streamable over http (possible with RTP)
        };

        // V A R I A B L E S
        private decimal bnsize;
        private decimal itimeval;
        private decimal rfgainval;
        private string wshapingval;
        private decimal cropval;
        private decimal ppmval;
        private string oldtextval;
        private string execute_command;
        public OxyPlot.WindowsForms.PlotView PlotHeatMap;
        public OxyPlot.WindowsForms.PlotView PlotSpectrumLine;

        List<decimal> maxhold_dB;
        List<decimal> minhold_dB;
        //public List<List<decimal>> store_dBs;
        List<List<decimal>> store_dBs = new List<List<decimal>>();
        List<List<decimal>> copy_dBs = new List<List<decimal>>();
        int iteration = 0;

        // EVENT HANDLER
        void plotModel_MouseDown(object sender, OxyPlot.OxyMouseEventArgs e)
        {
            Series serie = sender as Series;
            if (e.IsControlDown)
            {
               
                if (serie != null)
                {
                    OxyPlot.TrackerHitResult result = serie.GetNearestPoint(e.Position, true);
                    if (result != null)
                    {
                        // data point nearest to the click
                        var dataPoint = result.DataPoint.X;
                        //MessageBox.Show("Frequency: " + dataPoint);
                        numericUpDownFrequency.Value = (decimal)dataPoint;
                        numericUpDownTuneFrequency.Value = (decimal)dataPoint;
                        numericUpDownFreqRtl.Value = (decimal)dataPoint;
                    }
                }
            }
        }

        public PlotModel SpectrumLine(List<decimal> fqs, List<decimal> dBs, List<decimal> maxhold, List<decimal> minhold, bool autoscale, bool maxhTurnOn, bool minhTurnOn, int ymax, int ymin)
        {
            var plotModel1 = new PlotModel();
            //plotModel1.Title = "Spectrum Chart";
            // Define X-axe
            var linearAxis1 = new LinearAxis();
            linearAxis1.Position = AxisPosition.Bottom;
            linearAxis1.FontSize = 9;
            linearAxis1.IsAxisVisible = true;
            linearAxis1.StringFormat = "0.00";
            linearAxis1.IsZoomEnabled=false;
            linearAxis1.MajorGridlineStyle = LineStyle.Solid;
            // Define Y-axe
            var linearAxis2 = new LinearAxis();
            linearAxis2.MajorGridlineStyle = LineStyle.Solid;
            linearAxis2.MinorGridlineStyle = LineStyle.Dot;
            if (!autoscale)
            {
                linearAxis2.Maximum = ymax;
                linearAxis2.Minimum = ymin;
            }
            // Add axes to the plot
            plotModel1.Axes.Add(linearAxis1);
            plotModel1.Axes.Add(linearAxis2);
            //
            var lineSeries1 = new LineSeries();
            lineSeries1.TrackerFormatString = "Frequency={2:0.000}\nLevel={4:0.0}";
            //lineSeries1.Title = "Specrum line";
            // Spectrum line - Crimson
            lineSeries1.Color = OxyColor.FromRgb(220, 20, 60);
            lineSeries1.StrokeThickness = 0.1;
            //MaxHold line - Midnight Blue
            var lineSeries2 = new LineSeries();
            lineSeries2.Color = OxyColor.FromRgb(25, 25, 112);
            lineSeries2.StrokeThickness = 0.1;
            lineSeries2.LineStyle = LineStyle.Dot;
            //MinHold - Dark Blue
            var lineSeries3 = new LineSeries();
            lineSeries3.Color = OxyColor.FromRgb(105, 105, 105);
            lineSeries3.StrokeThickness = 0.1;
            lineSeries3.LineStyle = LineStyle.Dot;
            for (int i = 0; i < fqs.Count; i++)
            {
                var x = Convert.ToDouble(fqs[i]);
                if (checkBoxLine.Checked)
                {
                    var y = Convert.ToDouble(dBs[i]);
                    lineSeries1.Points.Add(new DataPoint(x, y));
                }
                
                if (maxhTurnOn)
                {
                    var ymaxhold = Convert.ToDouble(maxhold[i]);
                    lineSeries2.Points.Add(new DataPoint(x, ymaxhold));
                }

                if (minhTurnOn)
                {
                    var yminhold = Convert.ToDouble(minhold[i]);
                    lineSeries3.Points.Add(new DataPoint(x, yminhold));
                }
            }
            // Add line series to the Plot
            plotModel1.Series.Add(lineSeries1);
            plotModel1.Series.Add(lineSeries2);
            plotModel1.Series.Add(lineSeries3);
            // Add extension to MouseDown event. It gets X (frequency) and puts it in frequency control.
            lineSeries1.MouseDown += new EventHandler<OxyMouseDownEventArgs>(plotModel_MouseDown);
            return plotModel1;
        }

        public PlotModel HeatMapSeries(List<decimal> fqs, List<List<decimal>> array_dblistlist)
        {
            var plotModel1 = new PlotModel();
            //plotModel1.Subtitle = "dB";
            //plotModel1.Title = "Waterfall Chart";
            var linearColorAxis1 = new LinearColorAxis();
            linearColorAxis1.HighColor = OxyColors.Gray;
            linearColorAxis1.LowColor = OxyColors.Black;
            linearColorAxis1.Position = AxisPosition.Right;
            plotModel1.Axes.Add(linearColorAxis1);
            var linearAxis1 = new LinearAxis();
            linearAxis1.Position = AxisPosition.Top;
            linearAxis1.IsAxisVisible = false;
            plotModel1.Axes.Add(linearAxis1);
            var linearAxis2 = new LinearAxis();
            linearAxis2.Position = AxisPosition.Left;
            linearAxis2.StartPosition = 1;
            linearAxis2.EndPosition = 0;
            plotModel1.Axes.Add(linearAxis2);
            var heatMapSeries1 = new HeatMapSeries();
            heatMapSeries1.TrackerFormatString = "Frequency={2:0.000}\nLine={4:0.0}\nLevel={6:0.0}";

            heatMapSeries1.X0 = Convert.ToDouble(fqs.Min());
            heatMapSeries1.X1 = Convert.ToDouble(fqs.Max());
            heatMapSeries1.Y0 = 0;
            heatMapSeries1.Y1 = array_dblistlist.Count;
            heatMapSeries1.Interpolate = true;
            heatMapSeries1.Data = new Double[ fqs.Count, array_dblistlist.Count ]; // y-values, x-values
            heatMapSeries1.LabelFontSize = 0;
            for (int i = 0; i < array_dblistlist.Count; i++)
            {
                List<decimal> list_val = array_dblistlist[i];
                for (int j = 0; j < list_val.Count; j++)
                {
                    heatMapSeries1.Data[j, i] = Convert.ToDouble(list_val[j]);
                }
            }
            plotModel1.Series.Add(heatMapSeries1);
            // Add extension to MouseDown event. It gets X (frequency) and puts it in frequency control.
            heatMapSeries1.MouseDown += new EventHandler<OxyMouseDownEventArgs>(plotModel_MouseDown);
            return plotModel1;
        }

        // RESET CHARTS TO PREDEFINED STATE
        public void ResetCharts()
        {
            List<decimal> xlist = new List<decimal>();
            for (int i = 0; i < 100; i++)
            {
                xlist.Add(88 + i/5);
            }
            //
            List<List<decimal>> zlistlist = new List<List<decimal>>();
            for (int i = 0; i < 50; i++)
            {
                List<decimal> z_list = new List<decimal>();
                z_list.Add(-10);
                for (int j = 1; j < 100; j++)
                {
                    //z_list.Add(rnd.Next(-40, -39));
                    z_list.Add(-50);
                }
                zlistlist.Add(z_list);
            }
            PlotHeatMap.Model = HeatMapSeries(xlist, zlistlist);
            PlotSpectrumLine.Model = SpectrumLine(xlist, zlistlist[0], zlistlist[0], zlistlist[0], checkBoxAutoscale.Checked, checkBoxMaxHold.Checked, checkBoxMinHold.Checked,trackBarYmax.Value, trackBarYmin.Value);
            iteration = 0;
            store_dBs.Clear();
            richTextBoxResponse.Clear();
        }

        public FormPlayground()
        {
            InitializeComponent();
            // THIS IS TXBAND ComboBox ACTUALLY
            // Scan-Command comboBox
            comboBoxCommand.DataSource = scanBandBindingSource;
            comboBoxCommand.DisplayMember = "Name";
            comboBoxCommand.ValueMember = "Id"; 
            //////
            // Station Connection Parameters
            comboBoxStation.DisplayMember = "Name";
            comboBoxStation.ValueMember = "Id";
            //
            ////
            // RF gain - comboBox
            comboBoxRFgain.DataSource = new BindingSource(RFGainList, null);
            comboBoxRFgain.DisplayMember = "Key";
            comboBoxRFgain.ValueMember = "Value";
            // Integration time
            numericUpDownItime.Value = 1;
            // Bin size (Frequency step)
            numericUpDownFreqStep.Value = 50000;
            // Experimental rtl_power options
            checkBoxE4kOffset.Visible = false;
            checkBoxPeakHold.Visible = false;
            // ArcTan
            comboBoxArcTan.Text = "std";
            // Emphasize
            comboBoxEmphasize.Text = "option";
            // Window shaping
            comboBoxWShape.Text = "rectangular";
            // Modulation
            comboBoxModulation.Text = "fm";
            // FIR
            comboBoxFir.Text = "9";
            // Audio stream bandwidth
            //comboBoxStreamBW.SelectedItem = "128000";
            // Audio stream Codec
            comboBoxAudioCodec.DataSource = new BindingSource(AudioCodecList, null);
            comboBoxAudioCodec.DisplayMember = "Key";
            comboBoxAudioCodec.ValueMember = "Value";
            comboBoxAudioCodec.SelectedValue = "flac";
            // Charts Line Controls
            panelLineControl.Enabled = false;
            // Autoscale
            checkBoxAutoscale.Checked = true;
            // Plot Spectrum line
            checkBoxLine.Checked = true;
            // Scale Ymin
            trackBarYmin.Value = -40;
            // Scale Ymax
            trackBarYmax.Value = 5;
            // RTL-TCP tab initial values
            comboBoxSampleRateRtl.Text = "1024000";
            //
            checkedListBoxTcpSdr.SetItemChecked(0, true);
            //Set initial Location, Visibility and Height of Spectrum chart and RichTextBox
            richTextBoxResponse.Visible = false;
            // In Wingdings3 "$" is arrow down
            buttonTxtOnOff.Text = "+";
            panelChartSpectrumLine.Location = new Point(-2, 22);
            panelChartSpectrumLine.Height = 320;
            //
            //Chart Y controls
            labelYmax.Text = Convert.ToString(trackBarYmax.Value);
            labelYmin.Text = Convert.ToString(trackBarYmin.Value);
            // REMOVE FEATURES UNDER DEVELOPMENT
            //
            // HEATMAP CHART DRAW
            List<decimal> xlist = new List<decimal>();
            for (int i = 0; i < 100; i++)
            {
                xlist.Add(88 + i / 5);
            }
            //
            List<List<decimal>> zlistlist = new List<List<decimal>>();
            for (int i = 0; i < 50; i++)
            {
                List<decimal> z_list = new List<decimal>();
                z_list.Add(-10);
                for (int j = 1; j < 100; j++)
                {
                    //z_list.Add(rnd.Next(-40, -39));
                    z_list.Add(-50);
                }
                zlistlist.Add(z_list);
            }
            PlotHeatMap = new OxyPlot.WindowsForms.PlotView();
            // Preload some data to the HeatMap Graph
            PlotHeatMap.Model = HeatMapSeries(xlist, zlistlist);
            PlotHeatMap.Dock = DockStyle.Fill;
            // Add Waterfall Chart at Panel
            panelChartHeatMap.Controls.Add(PlotHeatMap);

            // SPECTRUM LINE CHART
            PlotSpectrumLine = new OxyPlot.WindowsForms.PlotView();
            // Preload some data to the Line Graph
            PlotSpectrumLine.Model = SpectrumLine(xlist, zlistlist[0], zlistlist[0], zlistlist[0], checkBoxAutoscale.Checked, checkBoxMaxHold.Checked, checkBoxMinHold.Checked,trackBarYmax.Value, trackBarYmin.Value);
            PlotSpectrumLine.Dock = DockStyle.Fill;
            // Add PlotSpectrumLine at Panel
            panelChartSpectrumLine.Controls.Add(PlotSpectrumLine);  
        }
        
        private List<decimal> myDrawSpectrum(string txtVal, decimal freqOffset)
        {
            List<decimal> dBs = new List<decimal>();
            List<decimal> fqs = new List<decimal>();

            List<List<decimal>> array_dblistlist = new List<List<decimal>>();
            var lines = txtVal.Split('\n');
            
            for (int i = 0; i < lines.Length; i++)
            {
                
                var oneline = lines[i];
                var elements = oneline.Split(',');
                // From the 6-th elements starts dB values ...
                for (int j = 6; j < elements.Length; j++)
                {
                    
                    // Date, Time, Hz_low, Hz_high, Hz_step, Samples, dB, dB, dB, ...
                    decimal freqlow = decimal.Parse(elements[2], CultureInfo.InvariantCulture);
                    //Console.WriteLine("===> FreqLow is: " + (freqlow - freqOffset));
                    freqlow -= freqOffset;
                    decimal step = decimal.Parse(elements[4], CultureInfo.InvariantCulture);
                    decimal dBval;
                    bool isNum = decimal.TryParse(elements[j], out dBval);
                    if (isNum)
                    {
                        dBval = decimal.Parse(elements[j], CultureInfo.InvariantCulture);
                        dBs.Add(dBval);
                    }
                    else
                    {
                        // Noise floor here...
                        dBs.Add(-35);
                    }
                    
                    decimal freq = (freqlow + step * (j - 6))/1000000;
                    fqs.Add(decimal.Round(freq, 3, MidpointRounding.AwayFromZero));
                    //Console.WriteLine(freq + ":" + dBval);
                }
            }
            iteration++;
            //// INITIALIZING ONLY IN FIRST WALK THROUGH
            int wflines = 20; // Number of WATERFALL Lines
            
            decimal minimal_dB = -50;
            if (dBs.Count > 0)
            {
                minimal_dB = dBs.Min();
            }
            
            if (iteration == 1)
            {
                // Populate Waterfall lines with default values
                for (int i = 0; i < wflines; i++)
                {
                    List<decimal> z_list = new List<decimal>();
                    for (int j = 0; j < dBs.Count; j++)
                    {
                        //z_list.Add(rnd.Next(-40, -39));
                        z_list.Add(minimal_dB);
                    }
                    store_dBs.Add(z_list);
                }
                store_dBs[0] = dBs;
                maxhold_dB = dBs; // In first iteration Max hold values are equal to first line of dBs
                
                minhold_dB = new List<decimal>();

                for (int i = 0; i < dBs.Count; i++)
                {
                    minhold_dB.Add(dBs.Max());
                    //Console.WriteLine("minhold value {0}", minhold_dB[i]);
                }
                    
            }
            else if (iteration > 1)
            {
                for (int i = wflines - 1; i > 0; i--)
                {
                    store_dBs[i] = store_dBs[i - 1];
                }
                store_dBs[0] = dBs;
                for (int k = 0; k < dBs.Count; k++)
                {
                    if (dBs[k] > maxhold_dB[k])
                    {
                        maxhold_dB[k] = dBs[k];
                    }
                    if (dBs[k] < minhold_dB[k])
                    {
                        minhold_dB[k] = dBs[k];
                        //Console.WriteLine("minhold: {0} - dB: {1}", minhold_dB[k], dBs[k]);
                    }
                 }
            }
            // Only If fqs and dBs are populated draw the Charts ...
            if (fqs.Count > 0 && dBs.Count > 0)
            {
                //// 
                Action plot_newdata = () => PlotHeatMap.Model = HeatMapSeries(fqs, store_dBs);
                PlotHeatMap.Invoke(plot_newdata);
                ////
                Action draw_spectrum = () => PlotSpectrumLine.Model = SpectrumLine(fqs, dBs, maxhold_dB, minhold_dB, checkBoxAutoscale.Checked, checkBoxMaxHold.Checked, checkBoxMinHold.Checked, trackBarYmax.Value, trackBarYmin.Value);
                PlotSpectrumLine.Invoke(draw_spectrum);
            }
            
            return dBs;
            //return fqs; // This is defined as public list
        }

        private void buttonExecute_Click(object sender, EventArgs e)
        {
            var rf_gain = comboBoxRFgain.SelectedValue;
            var ppmVal = numericUpDownPpm.Value;
            //if (textBoxUsername.Text == "" | textBoxPassword.Text == "" | comboBoxHostPort.Text == "" | comboBoxCommand.Text == "")
            if (Convert.ToString(comboBoxStation.SelectedValue).Trim() == "")
            {
                MessageBox.Show("Sorry! You must configure Measurement Stations List!");
            }
            else
            {
                progressBar1.Style = ProgressBarStyle.Marquee;
                progressBar1.MarqueeAnimationSpeed = 30;
                panelLineControl.Enabled = true;

                // Get Connection parameters from Database
                int stIdValue = Convert.ToInt32(comboBoxStation.SelectedValue);
                stationTableAdapter.FillById(mNCdataDataSet.Station, stIdValue);
                var row = mNCdataDataSet.Station.FirstOrDefault();
                // Default RF Gain and PPM
                comboBoxRFgain.SelectedValue = rf_gain;
                numericUpDownPpm.Value = ppmVal;
                //
                string host = row.Fqdn.Trim();
                string port = Convert.ToString(row.Port).Trim();
                string user = row.User.Trim();
                string passwd = row.Password.Trim();
                //
                List<string> prmssh = new List<string>();
                prmssh.Add(host);
                prmssh.Add(port);
                prmssh.Add(user);
                prmssh.Add(passwd);
                // Get Scan-band command from DataBase but only part related to Frequency start to stop ...
                int sbIdValue = Convert.ToInt32(comboBoxCommand.SelectedValue);
                scanBandTableAdapter.FillById(mNCdataDataSet.ScanBand, sbIdValue);
                var scbrow = mNCdataDataSet.ScanBand.FirstOrDefault();
                decimal frequencyOffset = numericUpDownFreqOffset.Value;
                string command = (scbrow.FreqStart + frequencyOffset)/ 1000000 + "M:" + (scbrow.FreqStop + frequencyOffset)/ 1000000 + "M";
                prmssh.Add(command);
                prmssh.Add(Convert.ToString(frequencyOffset));
                Console.WriteLine("The Execute button has been clicked and FreqOffset is: " + Convert.ToString(frequencyOffset));
                buttonExecute.Enabled = false;
                panelCmdOptions.Enabled = false;
                //numericUpDownFrequency.Enabled = false;
                numericUpDownSpan.Enabled = false;
                buttonStop.Enabled = !buttonExecute.Enabled;
                ResetCharts();
                this.backgroundWorkerSSH.RunWorkerAsync(prmssh);
            }
        }

        private void buttonExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }


        private void measurementToolStripMenuItem_Click(object sender, EventArgs e)
        {
            comboBoxCommand.DataSource = scanBandBindingSource;
            comboBoxCommand.DisplayMember = "Name";
            comboBoxCommand.ValueMember = "Id";
        }
        
        public string CurrentVersion
        {
            get
            {
            return ApplicationDeployment.IsNetworkDeployed
                   ? ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString()
                   : Assembly.GetExecutingAssembly().GetName().Version.ToString();
            }
        }      

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Monitoring Network Manager for Raspberry Pi - RTL-SDR based stations \n Author: Slaven Krilic <skrilic@outlook.com> \n Version: " + CurrentVersion);
        }

        private void backgroundWorkerSSH_DoWork(object sender, DoWorkEventArgs e)
        {
            List<string> prmssh = (List<string>)e.Argument;
            string host = prmssh[0];
            int port = Convert.ToInt16(prmssh[1]);
            string user = prmssh[2];
            string passwd = prmssh[3];
            string command = prmssh[4];
            string freqOffset = prmssh[5];

            PasswordConnectionInfo connectionInfo = new PasswordConnectionInfo(host, port, user, passwd);
            connectionInfo.Timeout = TimeSpan.FromSeconds(20);
            using (var client = new SshClient(connectionInfo))
            {
                //MessageBox.Show(command);
                try
                { 
                    client.Connect();
                    //
                    Action txtConStat_conText = () => textBoxConStat.Text = "CONNECTED!";
                    Action txtConStat_conColor = () => textBoxConStat.BackColor = Color.LightGreen;
                    textBoxConStat.Invoke(txtConStat_conText);
                    textBoxConStat.Invoke(txtConStat_conColor);
                    //
                    var noacu = client.RunCommand("who | wc -l"); // Number of active users already on system ...
                                                                  //MessageBox.Show("Number of connected users is: " + noacu.Result);             
                    if (Convert.ToInt16(noacu.Result) + 1 >= 2)
                    {
                        DialogResult result = MessageBox.Show("There is/are already connected " + noacu.Result + " user(s) on system. Are you sure You want to proceed!", "Confirmation", MessageBoxButtons.YesNo);
                        if (result == DialogResult.No)
                        {
                            client.Disconnect();
                            client.Dispose();
                            Action butnXEnable = () => buttonExecute.Enabled = true;
                            Action butnStopDisable = () => buttonStop.Enabled = false;
                            Action panelCmndEnable = () => panelCmdOptions.Enabled = true;
                            panelCmdOptions.Invoke(panelCmndEnable);
                            buttonExecute.Invoke(butnXEnable);
                            buttonStop.Invoke(butnStopDisable);
                        }
                    }
                        // Try to kill stalled commands ...
                        client.RunCommand("killall rtl_power");
                        client.RunCommand("killall rtl_fm");
                        //
                        var stalledcmd = client.RunCommand("ps aux | grep rtl_power |wc -l"); // Check if stalled measurement processes Exist
                                                                                                //MessageBox.Show("Number of rtl_power commands is/are: " + stalledcmd.Result);
                        if (Convert.ToUInt16(stalledcmd.Result) > 2)
                            {

                                DialogResult answer = MessageBox.Show(
                                    "Running process on the Measurement Station detected!\n"+
                                    "Maybe someone else is working now...\n"+
                                    "If You are sure there is no one else working\n"+
                                    "I Can try to Defrost remote system?",
                                    "What to do?", MessageBoxButtons.YesNo);
                                if (answer == DialogResult.Yes)
                                {
                                    MessageBox.Show("I'm going to try defrosting remote monitoring station, now!\n"+
                                        "Station is not going to be responsive for next cca 30sec\nPlease be patient!");
                                    client.RunCommand("sudo reboot");
                                }
                            }  
                        // Get values for rtl_power command...
                        // FREQUENCY STEP
                        Action get_binsize = () => bnsize = numericUpDownFreqStep.Value;
                        numericUpDownFreqStep.Invoke(get_binsize);
                        string binsize = Convert.ToString(bnsize);

                        // Integration Time
                        Action get_itime = () => itimeval = numericUpDownItime.Value;
                        numericUpDownItime.Invoke(get_itime);
                        string itime = Convert.ToString(itimeval);

                        // CROP
                        Action get_crop = () => cropval = numericUpDownCrop.Value;
                        numericUpDownCrop.Invoke(get_crop);
                        string crop = Convert.ToString(cropval);

                        // WINDOW SHAPING
                        Action get_wshaping = () => wshapingval = comboBoxWShape.Text;
                        comboBoxWShape.Invoke(get_wshaping);
                        string wshaping = Convert.ToString(wshapingval);

                        // PPM correction
                        Action get_ppm = () => ppmval = numericUpDownPpm.Value;
                        numericUpDownPpm.Invoke(get_ppm);
                        string ppm = Convert.ToString(ppmval);

                    List<List<decimal>> array_dblistlist = new List<List<decimal>>();
                        while (!backgroundWorkerSSH.CancellationPending)
                        {
                            // RF-GAIN
                            //Action get_rfgain = () => rfgainval = trackBarGain.Value;
                            //trackBarGain.Invoke(get_rfgain);
                            Action get_rfgain = () => rfgainval = Convert.ToDecimal(comboBoxRFgain.SelectedValue);
                            comboBoxRFgain.Invoke(get_rfgain);
                            string rfgain = Convert.ToString(rfgainval).Replace(',', '.');

                            Action txtConStat_Operation = () => textBoxConStat.Text = "RUNNING!";
                            textBoxConStat.Invoke(txtConStat_Operation);

                            if (backgroundWorkerSSH.CancellationPending)
                            {
                                e.Cancel = true;
                                return;
                            }
                            // Previous content of RichTextBox ...
                            Action get_oldtxtVal = () => oldtextval = richTextBoxResponse.Text;
                            richTextBoxResponse.Invoke(get_oldtxtVal);

                            if (!checkBoxAdvanced.Checked)
                            {
                                    if (checkBoxE4kOffset.Checked && checkBoxPeakHold.Checked) {
                                        execute_command = "rtl_power -O -P -p " + ppm.Replace(',', '.') + " -f " + command + ":" + binsize + "Hz" + " -i " + itime + " -g " + rfgain + " -c " + crop + "%" + " -w " + wshaping + " -1";
                                    }
                                    else if (checkBoxE4kOffset.Checked) {
                                        execute_command = "rtl_power -O -p " + ppm.Replace(',', '.') + " -f " + command + ":" + binsize + "Hz" + " -i " + itime + " -g " + rfgain + " -c " + crop + "%" + " -w " + wshaping + " -1";
                                    }
                                    else if (checkBoxPeakHold.Checked)
                                    {
                                        execute_command = "rtl_power -P -p " + ppm.Replace(',', '.') + " -f " + command + ":" + binsize + "Hz" + " -i " + itime + " -g " + rfgain + " -c " + crop + "%" + " -w " + wshaping + " -1";
                                    }
                                    else
                                    {
                                        execute_command = "rtl_power -p " + ppm.Replace(',', '.') + " -f " + command + ":" + binsize + "Hz" + " -i " + itime + " -g " + rfgain + " -c " + crop + "%" + " -w " + wshaping + " -1";
                                    }
                                
                                }
                            else
                            {
                                //Action freqControl_enabled = () => numericUpDownFrequency.Enabled = true;
                                //numericUpDownFrequency.Invoke(freqControl_enabled);
                                var fstart = Convert.ToDecimal(numericUpDownFrequency.Value) + Convert.ToDecimal(numericUpDownFreqOffset.Value/1000000) - Convert.ToDecimal(numericUpDownSpan.Value) / 2000;
                                var fstop = Convert.ToDecimal(numericUpDownFrequency.Value) + Convert.ToDecimal(numericUpDownFreqOffset.Value/1000000) + Convert.ToDecimal(numericUpDownSpan.Value) / 2000;
                                var cmdstr = fstart + "M:" + fstop + "M";
                                if (checkBoxE4kOffset.Checked && checkBoxPeakHold.Checked)
                                {
                                    execute_command = "rtl_power -O -P -p " + ppm.Replace(',', '.') + " -f " + cmdstr.Replace(',', '.') + ":" + binsize + "Hz" + " -i " + itime + " -g " + rfgain + " -c " + crop + "%" + " -w " + wshaping + " -1";
                                }
                                else if (checkBoxE4kOffset.Checked) {
                                    execute_command = "rtl_power -O -p " + ppm.Replace(',', '.') + " -f " + cmdstr.Replace(',', '.') + ":" + binsize + "Hz" + " -i " + itime + " -g " + rfgain + " -c " + crop + "%" + " -w " + wshaping + " -1";
                                }
                                else if (checkBoxPeakHold.Checked) {
                                    execute_command = "rtl_power -P -p " + ppm.Replace(',', '.') + " -f " + cmdstr.Replace(',', '.') + ":" + binsize + "Hz" + " -i " + itime + " -g " + rfgain + " -c " + crop + "%" + " -w " + wshaping + " -1";
                                }
                                else {
                                    execute_command = "rtl_power -p " + ppm.Replace(',', '.') + " -f " + cmdstr.Replace(',', '.') + ":" + binsize + "Hz" + " -i " + itime + " -g " + rfgain + " -c " + crop + "%" + " -w " + wshaping + " -1";
                                }
                        }
                            var console_text = client.RunCommand(execute_command);
                            var txtVal = console_text.Result;
                            Action show_response = () => richTextBoxResponse.Text = oldtextval + txtVal;
                            richTextBoxResponse.Invoke(show_response);
                            myDrawSpectrum(txtVal, Convert.ToDecimal(freqOffset));
                        }
                        client.Disconnect();
                        client.Dispose();

                        Action btnXEnable = () => buttonExecute.Enabled = true;
                        Action btnStopDisable = () => buttonStop.Enabled = false;
                        Action panelCmdEnable = () => panelCmdOptions.Enabled = true;
                        panelCmdOptions.Invoke(panelCmdEnable);
                        buttonExecute.Invoke(btnXEnable);
                        buttonStop.Invoke(btnStopDisable);

                }
                catch (Exception ex)
                {
                    Action btnXEnable = () => buttonExecute.Enabled = true;
                    Action btnStopDisable = () => buttonStop.Enabled = false;
                    Action panelCmdEnable = () => panelCmdOptions.Enabled = true;
                    panelCmdOptions.Invoke(panelCmdEnable);
                    buttonExecute.Invoke(btnXEnable);
                    buttonStop.Invoke(btnStopDisable);
                    MessageBox.Show("SSH Connection error!\n" + ex.Message);
                }
            }
        }

        // MEASUREMENT HAS COMPLETED
        private void backgroundWorkerSSH_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressBar1.Style = ProgressBarStyle.Continuous;
            progressBar1.MarqueeAnimationSpeed = 0;
            Action btnXEnable = () => buttonExecute.Enabled = true;
            Action btnStopDisable = () => buttonStop.Enabled = false;
            Action panelCmdEnable = () => panelCmdOptions.Enabled = true;
            buttonExecute.Invoke(btnXEnable);
            buttonStop.Invoke(btnStopDisable);
            panelCmdOptions.Invoke(panelCmdEnable);
            panelLineControl.Enabled = false;
            //numericUpDownFrequency.Enabled = true;
            numericUpDownSpan.Enabled = true;
            textBoxConStat.BackColor = Color.LightPink;
            textBoxConStat.Text = "DISCONNECTED";
            MessageBox.Show("The task has been completed!");
        }

        // START CANCELLATION
        private void buttonStop_Click(object sender, EventArgs e)
        {
            try
            {
                backgroundWorkerSSH.CancelAsync();
                backgroundWorkerSSH.Dispose();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Please Wait!\n Cancellation is in progress.\n" + ex.Message);
            }
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            saveFileDialogOutput.ShowDialog();
        }

        private void saveFileDialogOutput_FileOk(object sender, CancelEventArgs e)
        {
            string filename = saveFileDialogOutput.FileName;
            File.WriteAllText(filename, richTextBoxResponse.Text);
        }
        
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveFileDialogOutput.ShowDialog();
        }

        private void checkBoxAdvanced_Clicked(object sender, EventArgs e)
        {

        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            // AUDIO
            if (tabControl1.SelectedIndex != 1 && buttonAudioStart.Text == "Stop")
            {
                // This is going to stop running audio streaming ...
                buttonAudioStart.Text = "Start";
                groupBoxDongle.Enabled = true;
            }
            
            // SPECTRUM
            else if (tabControl1.SelectedIndex != 0 && !buttonExecute.Enabled)
            {
                backgroundWorkerSSH.CancelAsync();
                buttonExecute.Enabled = true;
                buttonStop.Enabled = false;
                panelCmdOptions.Enabled = true;
            }
            // RTL-TCP
            else if (tabControl1.SelectedIndex != 2 && buttonRtlTcp.Text == "Stop")
            {
                buttonRtlTcp.Text = "Start";
                groupBoxRtlTcp.Enabled = true;
            }
        }

        private void buttonAudioStart_Click(object sender, EventArgs e)
        {
            if (buttonAudioStart.Text == "Start") 
            { 
                if (Convert.ToString(comboBoxStation.SelectedValue) == "")
                {
                    MessageBox.Show("Sorry! You must configure Maesurement stations list!");
                }
                else
                {
                    // Default RF Gain and PPM
                    string rf_gain = Convert.ToString(comboBoxRFgain.SelectedValue);
                    var ppmVal = numericUpDownPpm.Value;
                    // Connection parameters
                    int IdValue = Convert.ToInt32(comboBoxStation.SelectedValue);
                    stationTableAdapter.FillById(mNCdataDataSet.Station, IdValue);
                    var row = mNCdataDataSet.Station.FirstOrDefault();
                    // Default RF Gain and PPM
                    comboBoxRFgain.SelectedValue = rf_gain;
                    numericUpDownPpm.Value = ppmVal;
                    //
                    string host = row.Fqdn.Trim();
                    string port = Convert.ToString(row.Port).Trim();
                    string user = row.User.Trim();
                    string passwd = row.Password.Trim();
                    // rtl_fm parameters
                    string tunefreq = Convert.ToString(this.numericUpDownTuneFrequency.Value + this.numericUpDownFreqOffset.Value/1000000);
                    string arcTan = Convert.ToString(comboBoxArcTan.SelectedItem);
                    string emphasize = Convert.ToString(comboBoxEmphasize.SelectedItem);
                    //string rf_gain = Convert.ToString(this.comboBoxRFgain.SelectedValue);
                    string demodulation = comboBoxModulation.Text;
                    string bandwidth = Convert.ToString(this.numericUpDownBW.Value);
                    string mediaPort = Convert.ToString(row.Media_port).Trim();
                    //string streamBw = Convert.ToString(comboBoxStreamBW.SelectedItem);
                    string streamAudioCodec = Convert.ToString(comboBoxAudioCodec.SelectedValue);
                    string ppmval = Convert.ToString(numericUpDownPpm.Value);
                    //

                    //
                    List<string> prms = new List<string>();
                    prms.Add(host);
                    prms.Add(port);
                    prms.Add(user);
                    prms.Add(passwd);
                    prms.Add(tunefreq);
                    prms.Add(rf_gain);
                    prms.Add(demodulation);
                    prms.Add(bandwidth);
                    prms.Add(mediaPort);
                    //prms.Add(streamBw);
                    prms.Add(streamAudioCodec);
                    prms.Add(arcTan);
                    prms.Add(emphasize);
                    prms.Add(ppmval);

                    //buttonAudioStart.Enabled = false;
                    buttonAudioStart.Text = "Stop";
                    groupBoxDongle.Enabled = false;
                    buttonAudioStart.Enabled = false;
                    this.backgroundWorkerAudio.RunWorkerAsync(prms);
                }
            }
            else if (buttonAudioStart.Text == "Stop")
            {
                buttonAudioStart.Text = "Start";
            }
        }

        private void backgroundWorkerAudio_DoWork(object sender, DoWorkEventArgs e)
        {
            List<string> prmssh = (List<string>)e.Argument;
            string host = prmssh[0];
            int port = Convert.ToInt16(prmssh[1]);
            string user = prmssh[2];
            string passwd = prmssh[3];
            string frequency = prmssh[4].Replace(',','.');
            string rfgain = prmssh[5];
            string modulation = prmssh[6];
            string bandwidth = prmssh[7];
            int mediaPort = Convert.ToInt16(prmssh[8]);
            string streamAudioCodec = prmssh[9];
            string arcTan = prmssh[10];
            string enableOption = prmssh[11];
            string ppmval = prmssh[12].Replace(',', '.');

            string FIR = string.Empty;
            string Squelch = string.Empty;
            string Resample = string.Empty;

            Action getFir = () => FIR = Convert.ToString(comboBoxFir.SelectedItem);
            comboBoxFir.Invoke(getFir);

            Action getSquelch = () => Squelch = Convert.ToString(numericUpDownSquelch.Value);
            numericUpDownSquelch.Invoke(getSquelch);

            Action getResample = () => Resample = Convert.ToString(numericUpDownResample.Value);
            numericUpDownResample.Invoke(getResample);
            int resamplekHz = (int)Math.Round(Convert.ToDecimal(Resample) / 1000);

            string estimatedStreamRate = string.Empty;
            if (streamAudioCodec == "vorb")
            {
                estimatedStreamRate = Convert.ToString((int)Math.Round(Convert.ToDecimal(Resample) / 1000));
            }
            else if (streamAudioCodec == "flac")
            {
                // FLAC compression is 40% to 50%. The number of bits per sample is 2x16 = 32
                estimatedStreamRate = Convert.ToString((int)Math.Round(Convert.ToDecimal(Resample) * 12.5M / 1000));
            }
            else
            {
                estimatedStreamRate = "N/A";
            }
            Action setTextStreamRate = () => textBoxEstimateBW.Text = estimatedStreamRate;
            textBoxEstimateBW.Invoke(setTextStreamRate);

            PasswordConnectionInfo connectionInfo = new PasswordConnectionInfo(host, port, user, passwd);
            connectionInfo.Timeout = TimeSpan.FromSeconds(20);

            using (var client = new SshClient(connectionInfo))
            {
                //MessageBox.Show(command);
                try
                {
                    client.Connect();
                    
                    // Configure Port Forwarding
                    string stream_address = "http://" + host + ":" + mediaPort + "/";
                    // "localhost", <local port>, "remote.net", <remote port>
                    var port_media = new ForwardedPortLocal("127.0.0.1", 8085, "127.0.0.1", Convert.ToUInt16(mediaPort));
                    if (checkBoxSshTunnel.Checked)
                    {  
                        client.AddForwardedPort(port_media);
                        port_media.Start();
                        stream_address = "http://127.0.0.1:8085/";
                    }
                    
                    client.RunCommand("killall rtl_fm");
                    client.RunCommand("killall vlc");
                    var noacu = client.RunCommand("who | wc -l"); // Number of active users already on system ...
                    //MessageBox.Show("Number of connected users is: " + noacu.Result);
                    if (Convert.ToInt16(noacu.Result) + 1 >= 2)
                    {
                        DialogResult result = MessageBox.Show("There is/are already connected " + noacu.Result + " user(s) on system. Are you sure You want to proceed!", "Confirmation", MessageBoxButtons.YesNo);
                        if (result == DialogResult.No)
                        {
                            client.Disconnect();
                            client.Dispose();
                            //Action butnXEnable = () => buttonExecute.Enabled = true;
                            //Action butnStopDisable = () => buttonStop.Enabled = false;
                            //Action panelCmndEnable = () => panelCmdOptions.Enabled = true;
                            //panelCmdOptions.Invoke(panelCmndEnable);
                            //buttonExecute.Invoke(butnXEnable);
                            //buttonStop.Invoke(butnStopDisable);
                            client.Disconnect();
                            client.Dispose();
                            Action btnStop2Start = () => buttonAudioStart.Text = "Start";
                            buttonAudioStart.Invoke(btnStop2Start);
                            Action btnXEnable = () => buttonAudioStart.Enabled = true;
                            buttonAudioStart.Invoke(btnXEnable);
                            Action grpboxDongleEnable = () => groupBoxDongle.Enabled = true;
                            groupBoxDongle.Invoke(grpboxDongleEnable);
                        }
                    }
                    //port_media.Start();
                    // Let's start rtl_fm and vlc ...
                    var streamshell = client.CreateShellStream("dumb", 80, 24, 800, 600, 4096);
                    var prompt = streamshell.Expect("$");
                    string rawFile = string.Empty;
                    Random rnd = new Random(); 
                    //Console.WriteLine("Got the prompt: " + prompt);
                    if (streamAudioCodec == "raw")
                    {
                        DateTime dateTimeNow = DateTime.Now;
                        string format = "yyyyMMddHHmm";
                        rawFile = Convert.ToString(dateTimeNow.ToString(format)) + Convert.ToString(rnd.Next(101, 200)) + ".raw";
                        string cmdString_rtlFM = String.Format("rtl_fm -M {0} -f {1}M -g {2} -s {3} -A {4} -E {5} -p {6} -F{7} -l {8} > {9}",
                            modulation, frequency, rfgain, bandwidth, arcTan, enableOption, Convert.ToString(ppmval), FIR, Squelch, rawFile);
                        //string cmdString_rtlFM = String.Format("rtl_fm -M {0} -f {1}M -g {2} -s {3} -r {4} -A {5} -E {6} -p {7} -F{8} -l {9} |",
                        //    modulation, frequency, rfgain, bandwidth, Convert.ToString(streamBw), arcTan, emphasize, Convert.ToString(ppmval), FIR, Squelch);
                        //string cmdString_VLC_part1 = "cvlc --intf dummy --demux=rawaud --rawaud-channels=1 --rawaud-samplerate=" + Convert.ToString(streamBw) + " - --sout \'#transcode{";
                        //string cmdString_VLC_part2 = String.Format("acodec={0}, ab={1}, channels=1, samplerate={2}", streamAudioCodec, Convert.ToString(streamBw / 1000), Convert.ToString(streamBw));
                        //string cmdString_VLC_part3 = "}:standard{access=http,mux=ogg,dst=0.0.0.0:" + mediaPort + "}\'";
                        //Console.WriteLine(cmdString_rtlFM);
                        streamshell.WriteLine(cmdString_rtlFM);
                        //Save to file ...
                        Action txtStreamLink_colorGreen = () => textBoxStreamLink.BackColor = Color.LightGreen;
                        textBoxStreamLink.Invoke(txtStreamLink_colorGreen);
                        Action txtStreamLink = () => textBoxStreamLink.Text = rawFile;
                        textBoxStreamLink.Invoke(txtStreamLink);
                    }
                    else
                    {
                        string cmdString_rtlFM = String.Format("rtl_fm -M {0} -f {1}M -g {2} -s {3} -r {4}k -A {5} -E {6} -p {7} -F{8} -l {9} | ",
                        modulation, frequency, rfgain, bandwidth, Convert.ToString(resamplekHz), arcTan, enableOption, Convert.ToString(ppmval), FIR, Squelch);
                        string cmdString_VLC_part1 = "cvlc --intf dummy --demux=rawaud --rawaud-channels=1 --rawaud-samplerate=" + Convert.ToString(resamplekHz*1000) + " - --sout \'#transcode{";
                        string cmdString_VLC_part2 = String.Format("acodec={0},ab={1},channels=1,samplerate={2}", streamAudioCodec, Convert.ToString(resamplekHz), Convert.ToString(resamplekHz * 1000));
                        //string cmdString_VLC_part2 = String.Format("acodec={0}, ab={1}", streamAudioCodec, Convert.ToString(resamplekHz));
                        string cmdString_VLC_part3 = "}:standard{access=http,mux=ogg,dst=0.0.0.0:" + mediaPort + "}\'";
                        //var command = "/home/pi/startFM.sh " + modulation + " " + frequency + "M " + rfgain + " " + bandwidth + "k " + Convert.ToString(streamBw) + " " + Convert.ToString(streamBw/1000);
                        //Console.WriteLine(cmdString_rtlFM + cmdString_VLC_part1 + cmdString_VLC_part2 + cmdString_VLC_part3);
                        streamshell.WriteLine(cmdString_rtlFM + cmdString_VLC_part1 + cmdString_VLC_part2 + cmdString_VLC_part3);
                        // Now start playing ...
                        Action txtStreamLink_colorGreen = () => textBoxStreamLink.BackColor = Color.LightGreen;
                        textBoxStreamLink.Invoke(txtStreamLink_colorGreen);
                        Action txtStreamLink = () => textBoxStreamLink.Text = stream_address;
                        textBoxStreamLink.Invoke(txtStreamLink);
                    }

                    Action btnAudioStartEnable = () => buttonAudioStart.Enabled = true;
                    buttonAudioStart.Invoke(btnAudioStartEnable);
                    while (buttonAudioStart.Text == "Stop" && client.IsConnected)
                    {
                        continue;
                    }
                    Action txtStreamClear = () => textBoxStreamLink.Text = "";
                    textBoxStreamLink.Invoke(txtStreamClear);
                    Action txtStreamLink_colorRed = () => textBoxStreamLink.BackColor = Color.LightPink;
                    textBoxStreamLink.Invoke(txtStreamLink_colorRed);
                    //
                    if (checkBoxSshTunnel.Checked)
                    {
                        port_media.Stop();
                    }
                    streamshell.Close();
                    Action txtEstRateClear = () => textBoxEstimateBW.Text = "";
                    textBoxStreamLink.Invoke(txtEstRateClear);
                    client.RunCommand("killall rtl_fm");
                    client.RunCommand("killall vlc");
                    client.Disconnect();
                    client.Dispose();
                }
                catch (Exception ex)
                {
                    Action btnStop2Start = () => buttonAudioStart.Text = "Start";
                    buttonAudioStart.Invoke(btnStop2Start);
                    Action btnXEnable = () => buttonAudioStart.Enabled = true;
                    buttonAudioStart.Invoke(btnXEnable);
                    Action grpboxDongleEnable = () => groupBoxDongle.Enabled = true;
                    groupBoxDongle.Invoke(grpboxDongleEnable);
                    MessageBox.Show("Error!\n" + ex.Message);
                }
            }
        }

        private void backgroundWorkerAudio_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            buttonAudioStart.Enabled = true;
            groupBoxDongle.Enabled = true;
        }

        private void measurementSystemsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ConfigForm cform = new ConfigForm();
            cform.Show();
        }

        private void scanBandsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormScanBandConfig scbform = new FormScanBandConfig();
            scbform.Show();
        }

        private void FormPlayground_Load(object sender, EventArgs e)
        {
            // TODO: This line of code loads data into the 'mNCdataDataSet.Station' table. You can move, or remove it, as needed.
            this.stationTableAdapter.Fill(this.mNCdataDataSet.Station);
            // TODO: This line of code loads data into the 'mNCdataDataSet.ScanBand' table. You can move, or remove it, as needed.
            this.scanBandTableAdapter.Fill(this.mNCdataDataSet.ScanBand);
        }

        private void stations_reLoad(object sender, EventArgs e)
        {
            // TODO: This line of code loads data into the 'mNCdataDataSet.Station' table. You can move, or remove it, as needed.
            this.stationTableAdapter.Fill(this.mNCdataDataSet.Station);
        }

        private void scanBand_reLoad(object sender, EventArgs e)
        {
            // TODO: This line of code loads data into the 'mNCdataDataSet.ScanBand' table. You can move, or remove it, as needed.
            this.scanBandTableAdapter.Fill(this.mNCdataDataSet.ScanBand);
        }

        private void antennaDBToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void remoteAdministrationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormMaintenance maintform = new FormMaintenance();
            maintform.Show();
        }

        private void comboBoxStation_SelectedIndexChanged(object sender, EventArgs e)
        {
            int IdStation = Convert.ToInt32(comboBoxStation.SelectedValue);
            var rfgain = stationTableAdapter.FillByID_RFgain(IdStation);
            var ppmIni = stationTableAdapter.FillByID_Ppm(IdStation);
            numericUpDownPpm.Value = Convert.ToDecimal(ppmIni);
            comboBoxRFgain.SelectedIndex = comboBoxRFgain.FindStringExact(Convert.ToString(rfgain)); 
        }

        private void numericUpDownTuneFrequency_MouseClick(object sender, MouseEventArgs e)
        {
            if (Control.ModifierKeys == Keys.Control)
            {
                numericUpDownTuneFrequency.Value = numericUpDownFrequency.Value;
            }
        }

        private void checkBoxAutoscale_CheckStateChanged(object sender, EventArgs e)
        {
            if (checkBoxAutoscale.Checked)
            {
                groupBoxY.Enabled = false;
            }
            else
            {
                groupBoxY.Enabled = true;
            }
        }


        private void buttonTxtOnOff_Click(object sender, EventArgs e)
        {
            // Rich Text Box is Visible
            if (buttonTxtOnOff.Text == "-")
            {
                richTextBoxResponse.Visible = false;
                buttonTxtOnOff.Text = "+";
                panelChartSpectrumLine.Location = new Point(-2, 22);
                panelChartSpectrumLine.Height += richTextBoxResponse.Height;
            }
            else if (buttonTxtOnOff.Text == "+")
            {
                richTextBoxResponse.Visible = true;
                buttonTxtOnOff.Text = "-";
                panelChartSpectrumLine.Location = new Point(-2, 126);
                panelChartSpectrumLine.Height -= richTextBoxResponse.Height;
            }
        }

        private void trackBarYmax_ValueChanged(object sender, EventArgs e)
        {
            labelYmax.Text = Convert.ToString(trackBarYmax.Value);
            trackBarYmin.Maximum = trackBarYmax.Value - 5;
        }

        private void trackBarYmin_ValueChanged(object sender, EventArgs e)
        {
            labelYmin.Text = Convert.ToString(trackBarYmin.Value);
            trackBarYmax.Minimum = trackBarYmin.Value + 5;
        }

        private void checkBoxAdvanced_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxAdvanced.Checked)
            {
                panelAdvanced.Enabled = true;
                numericUpDownFreqStep.Value = 1000;
                //numericUpDownFrequency.Enabled = true;
                //numericUpDownSpan.Enabled = true;
                comboBoxCommand.Enabled = false; // ScanBand
            }
            else
            {
                panelAdvanced.Enabled = false;
                numericUpDownFreqStep.Value = 10000;
                //numericUpDownFrequency.Enabled = false;
                //numericUpDownSpan.Enabled = false;
                comboBoxCommand.Enabled = true; // ScanBand
            }
        }

        private void checkBoxMaxHold_CheckedChanged(object sender, EventArgs e)
        {
            if (store_dBs.Count > 0)
            {
                for (int i = 0; i < maxhold_dB.Count; i++)
                {
                    maxhold_dB[i] = maxhold_dB.Min() - 5;
                }
            }    
            
        }

        private void checkBoxMinHold_CheckedChanged(object sender, EventArgs e)
        {
            if (store_dBs.Count < 0)
            {
                for (int i = 0; i < minhold_dB.Count; i++)
                {
                    minhold_dB[i] = minhold_dB.Max() + 5;
                }
            } 
        }

        private void numericUpDownFrequency_ValueChanged(object sender, EventArgs e)
        {
            if (store_dBs.Count > 0) 
            {
                for (int i = 0; i < maxhold_dB.Count; i++)
                {
                    //maxhold_dB[i] = maxhold_dB.Min() - 5;
                    //minhold_dB[i] = minhold_dB.Max() + 5;
                    maxhold_dB[i] = trackBarYmin.Value - 5;
                    minhold_dB[i] = trackBarYmax.Value + 5;
                }
            }
            
        }

        private void buttonRtlTcp_Click(object sender, EventArgs e)
        {
            if (buttonRtlTcp.Text == "Start")
            {
                string commandToStart = string.Empty;
                // Connection parameters
                int rtlIdValue = Convert.ToInt32(comboBoxStation.SelectedValue);
                stationTableAdapter.FillById(mNCdataDataSet.Station, rtlIdValue);
                var row = mNCdataDataSet.Station.FirstOrDefault();
                //Console.WriteLine(row.Fqdn.Trim() + "," + row.Port.Trim() + "," + row.User.Trim() + "," + row.Password.Trim());
                //
                string host = row.Fqdn.Trim();
                string port = Convert.ToString(row.Port).Trim();
                string user = row.User.Trim();
                string passwd = row.Password.Trim();
                string mediaPort = Convert.ToString(row.Media_port).Trim();
                //
                var rfgain = stationTableAdapter.FillByID_RFgain(rtlIdValue);
                var ppmVal = stationTableAdapter.FillByID_Ppm(rtlIdValue);
                numericUpDownPpm.Value = Convert.ToDecimal(ppmVal);
                comboBoxRFgain.SelectedIndex = comboBoxRFgain.FindStringExact(Convert.ToString(rfgain));
                //string rfgain = stationTableAdapter.FillByID_RFgain(rtlIdValue);
                //string ppmVal = Convert.ToString(row.Ppm);
                //
                List<string> prms = new List<string>();
                prms.Add(host);
                prms.Add(port);
                prms.Add(user);
                prms.Add(passwd);
                prms.Add(Convert.ToString(rfgain));
                prms.Add(Convert.ToString(ppmVal));
                //buttonRtlTcp.Enabled = false;
                buttonRtlTcp.Text = "Stop";
                groupBoxRtlTcp.Enabled = false;
                buttonRtlTcp.Enabled = false;
                foreach (int indexChecked in checkedListBoxTcpSdr.CheckedIndices)
                {
                    if (indexChecked == 0)
                    {
                        commandToStart = "rtl_tcp";
                    }
                    else if (indexChecked == 1)
                    {
                        commandToStart = "rtl_sdr";
                    }
                }
                prms.Add(commandToStart);
                prms.Add(mediaPort);

                backgroundWorkerRtlTcp.RunWorkerAsync(prms);
            }
            else if (buttonRtlTcp.Text == "Stop")
            {
                buttonRtlTcp.Text = "Start";
            }
        }

        private void backgroundWorkerRtlTcp_DoWork(object sender, DoWorkEventArgs e)
        {
            string outFile = string.Empty;
            //
            List<string> prmssh = (List<string>)e.Argument;
            string host = prmssh[0];
            int port = Convert.ToInt16(prmssh[1]);
            string user = prmssh[2];
            string passwd = prmssh[3];
            string rfgain = prmssh[4];
            string ppmVal = prmssh[5];
            string cmdToStart = prmssh[6];
            string mediaPort = prmssh[7];

            Random rnd = new Random();
            PasswordConnectionInfo connectionInfo = new PasswordConnectionInfo(host, port, user, passwd);
            connectionInfo.Timeout = TimeSpan.FromSeconds(20);

            using (var client = new SshClient(connectionInfo))
            {
                //MessageBox.Show(command);
                try
                {
                    client.Connect();

                    // Configure Port Forwarding
                    string stream_address = host + ":" + mediaPort;
                    // "localhost", <local port>, "remote.net", <remote port>
                    var port_media = new ForwardedPortLocal("127.0.0.1", 1234, "127.0.0.1", Convert.ToUInt16(mediaPort));
                    if (checkBoxSshTunRtl.Checked)
                    {
                        client.AddForwardedPort(port_media);
                        port_media.Start();
                        stream_address = "127.0.0.1:1234";
                    }

                    client.RunCommand("killall rtl_fm");
                    client.RunCommand("killall vlc");
                    client.RunCommand("killall rtl_tcp");
                    client.RunCommand("killall rtl_sdr");
                    client.RunCommand("killall rtl_power");
                   
                    var noacu = client.RunCommand("who | wc -l"); // Number of active users already on system ...
                    //MessageBox.Show("Number of connected users is: " + noacu.Result);
                    if (Convert.ToInt16(noacu.Result) + 1 >= 2)
                    {
                        DialogResult result = MessageBox.Show("There is/are already connected " + noacu.Result + " user(s) on system. Are you sure You want to proceed!", "Confirmation", MessageBoxButtons.YesNo);
                        if (result == DialogResult.No)
                        {
                            client.Disconnect();
                            client.Dispose();
                            client.Disconnect();
                            client.Dispose();
                            Action btnStop2Start = () => buttonRtlTcp.Text = "Start";
                            buttonRtlTcp.Invoke(btnStop2Start);
                            Action btnXEnable = () => buttonRtlTcp.Enabled = true;
                            buttonRtlTcp.Invoke(btnXEnable);
                            Action grpboxRtlTcpEnable = () => groupBoxRtlTcp.Enabled = true;
                            groupBoxRtlTcp.Invoke(grpboxRtlTcpEnable);
                        }
                    }
                    // Let's start rtl_tcp ...
                    var streamshell = client.CreateShellStream("dumb", 80, 24, 800, 600, 4096);
                    //var prompt = streamshell.Expect("$");
                    streamshell.Expect("$");
                    //Console.WriteLine("Got the prompt: " + prompt);
                    //
                    string freqRtl = string.Empty;
                    Action freqRtlGet = () => freqRtl = Convert.ToString(numericUpDownFreqRtl.Value + numericUpDownFreqOffset.Value / 1000000);
                    Invoke(freqRtlGet);
                    //
                    string sampleRateRtl = string.Empty;
                    Action sampleRateRtlGet = () => sampleRateRtl = comboBoxSampleRateRtl.Text;
                    Invoke(sampleRateRtlGet);
                    //
                    string rfGain = string.Empty;
                    Action rfGainGetVal = () => rfGain = Convert.ToString(comboBoxRFgain.Text);
                    Invoke(rfGainGetVal);
                    
                    if (cmdToStart == "rtl_tcp")
                    {
                        string cmdString_rtltcp = String.Format("rtl_tcp -g {0} -P {1} -f {2} -s {3} -a 0.0.0.0 -p {4}", rfGain, ppmVal.Replace(',', '.'), freqRtl.Replace(',', '.'), sampleRateRtl, mediaPort);
                        streamshell.WriteLine(cmdString_rtltcp);
                        // Start IQ data streaming ...
                        Action txtRtlTcp_colorGreen = () => textBoxRtlTcp.BackColor = Color.LightGreen;
                        textBoxRtlTcp.Invoke(txtRtlTcp_colorGreen);
                        Action txtRtlTcp = () => textBoxRtlTcp.Text = stream_address;
                        textBoxRtlTcp.Invoke(txtRtlTcp);
                    }
                    else if (cmdToStart == "rtl_sdr")
                    {
                        DateTime dateTimeNow = DateTime.Now;
                        string format = "yyyyMMddHHmm";
                        outFile = Convert.ToString(dateTimeNow.ToString(format)) + Convert.ToString(rnd.Next(101, 200)) + ".bin";
                      
                        string cmdString_rtltcp = String.Format("rtl_sdr -g {0} -p {1} -f {2} -s {3} {4}", rfGain, ppmVal.Replace(',', '.'), freqRtl.Replace(',', '.'), sampleRateRtl, outFile);
                        streamshell.WriteLine(cmdString_rtltcp);
                        // Start recording IQ data ...
                        Action txtRtlTcp_colorGreen = () => textBoxRtlTcp.BackColor = Color.LightGreen;
                        textBoxRtlTcp.Invoke(txtRtlTcp_colorGreen);
                        Action txtRtlTcp = () => textBoxRtlTcp.Text = outFile;
                        textBoxRtlTcp.Invoke(txtRtlTcp);
                    }
                    //
                    Action btnRtlTcpEnable = () => buttonRtlTcp.Enabled = true;
                    buttonRtlTcp.Invoke(btnRtlTcpEnable);

                    //string shellString = streamshell.Expect("Signal caught, exiting!");
                    while (buttonRtlTcp.Text == "Stop" && client.IsConnected)
                    {
                        //Console.WriteLine("I am in the loop!");
                        //if (streamshell.Expect("Signal caught, exiting!") == "Signal caught, exiting!")
                        //{
                        //    port_media.Stop();
                        //    streamshell.Close();
                        //    client.Disconnect();
                        //    client.Dispose();
                        //    Action txtRtlClear = () => textBoxRtlTcp.Text = "";
                        //    textBoxRtlTcp.Invoke(txtRtlClear);
                        //    Action txtRtl_colorRed = () => textBoxRtlTcp.BackColor = Color.LightPink;
                        //    textBoxStreamLink.Invoke(txtRtl_colorRed);
                        //    Action btnStop2Start = () => buttonRtlTcp.Text = "Start";
                        //    buttonRtlTcp.Invoke(btnStop2Start);
                        //    MessageBox.Show("Signal caught, exiting!\nYou've just disconnected from rtl_tcp service on the Station?!\nIf You wish to proceed, please press the Start button again!");
                        //}
                        //else
                        //{
                            continue;
                        //}
                    }
                    Action txtRtlTcpClear = () => textBoxRtlTcp.Text = "";
                    textBoxRtlTcp.Invoke(txtRtlTcpClear);
                    Action txtRtlTcp_colorRed = () => textBoxRtlTcp.BackColor = Color.LightPink;
                    textBoxStreamLink.Invoke(txtRtlTcp_colorRed);
                    //
                    port_media.Stop();
                    streamshell.Close();
                    client.Disconnect();
                    client.Dispose();
                }
                catch (Exception ex)
                {
                    Action btnStop2Start = () => buttonRtlTcp.Text = "Start";
                    buttonRtlTcp.Invoke(btnStop2Start);
                    Action btnXEnable = () => buttonRtlTcp.Enabled = true;
                    buttonRtlTcp.Invoke(btnXEnable);
                    Action grpboxRtlTcpEnable = () => groupBoxRtlTcp.Enabled = true;
                    groupBoxRtlTcp.Invoke(grpboxRtlTcpEnable);
                    MessageBox.Show("Error!\n" + ex.Message);
                }
            }
        }

        private void backgroundWorkerRtlTcp_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            buttonRtlTcp.Enabled = true;
            groupBoxRtlTcp.Enabled = true;
        }

        private void checkedListBoxTcpSdr_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if (e.NewValue == CheckState.Checked)
                for (int ix = 0; ix < checkedListBoxTcpSdr.Items.Count; ++ix)
                    if (e.Index != ix) checkedListBoxTcpSdr.SetItemChecked(ix, false);
        }

        private void comboBoxAudioCodec_SelectedValueChanged(object sender, EventArgs e)
        {
            if (Convert.ToString(comboBoxAudioCodec.SelectedValue) == "raw")
            {
                numericUpDownResample.Enabled = false;
            }
            else
            {
                numericUpDownResample.Enabled = true;
            }
        }

        private void documentationToolStripMenuItem_Click(object sender, EventArgs e)
        { 
            try
            {
                System.Diagnostics.Process.Start("https://bitbucket.org/slaven_krilic/mnm4sdr/wiki/Home");
            }
            catch { }
    }

        private void numericUpDownFreqOffset_ValueChanged(object sender, EventArgs e)
        {
            if (numericUpDownFreqOffset.Value > 0)
            {
                numericUpDownFrequency.Maximum = 300000 - numericUpDownFreqOffset.Value/ 1000000;
                numericUpDownFreqRtl.Maximum = 300000 - numericUpDownFreqOffset.Value / 1000000;
                numericUpDownTuneFrequency.Maximum = 300000 - numericUpDownFreqOffset.Value / 1000000;
            }
            else if (numericUpDownFreqOffset.Value < 0)
            {
                numericUpDownFrequency.Minimum = Math.Abs(numericUpDownFreqOffset.Value / 1000000);
                numericUpDownFreqRtl.Minimum = Math.Abs(numericUpDownFreqOffset.Value / 1000000);
                numericUpDownTuneFrequency.Minimum = Math.Abs(numericUpDownFreqOffset.Value / 1000000);
            }
        }

        private void numericUpDownResample_Click(object sender, EventArgs e)
        {
            numericUpDownResample.Maximum = numericUpDownBW.Value;
        }

        private void checkBoxSshTunnel_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void comboBoxAudioCodec_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (Convert.ToString(comboBoxAudioCodec.SelectedValue) == "vorb" && numericUpDownResample.Value > 16000)
            {
                MessageBox.Show("You've selected OGG!\nIf your station is an Raspberry PI\nPlease, be advised to not set\nmore than 12000 as Resampling rate!\nBecause of high CPU usage.",
                    "ATTENTION - RASPBERRY-Pi USERS");
            }
        }
    }
}
